using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using XDL.Framework.Collections;
using Microsoft.Xna.Framework.Content;
using XDL.Framework.Messaging;
using Microsoft.Xna.Framework.Graphics;

namespace XDL.Framework
{
    /// <summary>
    /// Helper class to access various game <see cref="Service"/>'s and the global <see cref="Game"/> instance.
    /// </summary>
    public class GameServices
    {
        static List<ContentManager> m_altContents = new List<ContentManager>();
        static EventDispatcher m_eventDispatcher = new EventDispatcher();

        public static ContentManager RegisterContentFolder(string rootDirectory)
        {
            ContentManager content = new ContentManager(m_game.Services, rootDirectory);
            m_altContents.Insert(0, content);
            return content;
        }

        /// <summary>
        /// Event dispatcher
        /// </summary>
        static public EventDispatcher EventDispatcher
        {
            get
            {
                return m_eventDispatcher;
            }
        }

        static public Viewport Viewport
        {
            get;
            set;
        }

        /// <summary>
        /// Enable support for named services.
        /// </summary>
        /// <param name="game">Underlying game engine.</param>
        public static void EnableNamedServices(Game game)
        {
            m_game = game;

            NamedServiceContainer nsc = new NamedServiceContainer();
            m_game.Services.AddService(typeof(NamedServiceContainer), nsc);
            RegisterContentFolder("XDLContent");
        }

        /// <summary>
        /// Returns a registered service.
        /// </summary>
        /// <typeparam name="T">Service type</typeparam>
        /// <returns>A service instance or null</returns>
        public static T GetService<T>() where T:class
        {
            return m_game.Services.GetService(typeof(T)) as T;
        }

        /// <summary>
        /// Returns a named service.
        /// </summary>
        /// <typeparam name="T">Service type</typeparam>
        /// <param name="name">Service name</param>
        /// <returns></returns>
        /// <remarks>
        /// A <see cref="NamedServiceContainer"/> must have been previously added to the provider list.
        /// </remarks>
        public static T GetService<T>(string name) where T : class
        {
            NamedServiceContainer nsc = GetService<NamedServiceContainer>();
            return nsc.GetService<T>(name);
        }

        public static T LoadContent<T>(string name)
        {
            foreach (ContentManager it in m_altContents)
            {
                try
                {
                    return it.Load<T>(name);
                }
                catch (ContentLoadException)
                {
                    // move to next content set
                }
            }
            throw new ContentLoadException(string.Format("Unable to find: {0} in the register content sets.", name));
        }

        /// <summary>
        /// Helper to register a named service provider.
        /// </summary>
        /// <param name="name">Service name.</param>
        /// <param name="provider">Service provider instance.</param>
        /// <remarks>
        /// A <see cref="NamedServiceContainer"/> must have been previously added to the provider list.
        /// </remarks>
        public static void AddService(string name, object provider)
        {
            NamedServiceContainer nsc = GetService<NamedServiceContainer>();
            nsc.AddService(name, provider);
        }

        /// <summary>
        /// Stores the unique game instance.
        /// </summary>
        static Game m_game = null;

        /// <summary>
        /// Gets the unique game instance.
        /// </summary>
        public static Game Game
        {
            get
            {
                return m_game;
            }
        }

        public static void Unload()
        {
            m_game = null;
        }

#if DEBUG
        public static bool Dump = false;
        public static bool DebugDraw = false;
        public static bool LockCam = false;
#else
        public const bool Dump = false;
        public const bool DebugDraw = false;
        public const bool LockCam = false;
#endif

        public static TimeSpan RenderingTime = TimeSpan.Zero;
        public static TimeSpan UpdateTime = TimeSpan.Zero;
    }
}
